﻿using System;
using System.Xml.XPath;

namespace Songhay.Data.GenericWeb.InputDefinitions
{
    using Songhay.Data.GenericWeb.DataTransferContracts;
    using Songhay.Xml;

    /// <summary>
    /// Defines input for the Fragment data transfer contract.
    /// </summary>
    public class InputFragment : IFragment
    {
        /// <summary>
        /// Processes data for the delete command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Fragment data transfer contract.</returns>
        public static IFragment InputDelete(IXPathNavigable navigableInput)
        {
            InputFragment inputFragment = new InputFragment();
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            int? id = FrameworkType.ParseInt32(XmlUtility.GetNodeValue(node, "./FragmentId", true));
            inputFragment.FragmentId = id;

            return inputFragment;
        }

        /// <summary>
        /// Processes data for the insert command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Fragment data transfer contract.</returns>
        public static IFragment InputInsert(IXPathNavigable navigableInput)
        {
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            InputFragment inputFragment = new InputFragment();

            object p = null;
            p = XmlUtility.GetNodeValue(node, "./FragmentName", true);
            inputFragment.FragmentName = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./FragmentDisplayName", true);
            inputFragment.FragmentDisplayName = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./SortOrdinal", true);
            inputFragment.SortOrdinal = FrameworkType.ParseByte(p);

            p = XmlUtility.GetNodeValue(node, "./ItemChar", true); //TODO: enforce string-length for ItemChar
            inputFragment.ItemChar = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./ItemText", true);
            inputFragment.ItemText = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValueAndParse<DateTime>(node, "./CreateDate", true, DateTime.Now);
            inputFragment.CreateDate = FrameworkType.ParseDateTime(p);

            p = XmlUtility.GetNodeValue(node, "./EndDate", true);
            inputFragment.EndDate = FrameworkType.ParseDateTime(p);

            p = XmlUtility.GetNodeValueAndParse<DateTime>(node, "./ModificationDate", true, DateTime.Now);
            inputFragment.ModificationDate = FrameworkType.ParseDateTime(p);

            p = XmlUtility.GetNodeValue(node, "./DocumentId", true);
            inputFragment.DocumentId = FrameworkType.ParseInt32(p);

            p = XmlUtility.GetNodeValue(node, "./PrevFragmentId", true);
            inputFragment.PrevFragmentId = FrameworkType.ParseInt32(p);

            p = XmlUtility.GetNodeValue(node, "./NextFragmentId", true);
            inputFragment.NextFragmentId = FrameworkType.ParseInt32(p);

            p = XmlUtility.GetNodeValue(node, "./IsPrevious", true);
            inputFragment.IsPrevious = FrameworkType.ParseBoolean(p, true);

            p = XmlUtility.GetNodeValue(node, "./IsNext", true);
            inputFragment.IsNext = FrameworkType.ParseBoolean(p, true);

            p = XmlUtility.GetNodeValue(node, "./IsWrapper", true);
            inputFragment.IsWrapper = FrameworkType.ParseBoolean(p, true);

            p = XmlUtility.GetNodeValue(node, "./ClientId", true);
            inputFragment.ClientId = FrameworkType.ParseString(p);

            p = XmlUtility.GetNodeValue(node, "./IsActive", true);
            inputFragment.IsActive = FrameworkType.ParseBoolean(p, true);

            return inputFragment;
        }

        /// <summary>
        /// Processes data for the update command.
        /// </summary>
        /// <param name="navigableInput">The navigable input.</param>
        /// <returns>Returns the Fragment data transfer contract.</returns>
        public static IFragment InputUpdate(IXPathNavigable navigableInput)
        {
            XPathNavigator node = XmlUtility.GetNavigableNode(navigableInput, "//FormData");

            IFragment inputFragment = InputFragment.InputInsert(navigableInput);

            object p = null;

            p = XmlUtility.GetNodeValue(node, "./FragmentId", true);

            if(FrameworkType.ObjectIsNullOrEmptyString(p))
                throw new Exception("Fragment ID cannot be null or empty.");

            inputFragment.FragmentId = FrameworkType.ParseInt32(p);

            return inputFragment;
        }

        #region IFragment Members

        /// <summary>
        /// Gets or sets the Client ID.
        /// </summary>
        /// <value>The Client ID.</value>
        public string ClientId
        {
            get
            {
                return this._clientId;
            }
            set
            {
                this._clientId = value;
            }
        }

        /// <summary>
        /// Gets or sets the create date.
        /// </summary>
        /// <value>The create date.</value>
        public DateTime? CreateDate
        {
            get
            {
                return this._createDate;
            }
            set
            {
                this._createDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the Document ID.
        /// </summary>
        /// <value>The Document ID.</value>
        public int? DocumentId
        {
            get
            {
                return this._documentId;
            }
            set
            {
                this._documentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the end date.
        /// </summary>
        /// <value>The end date.</value>
        public DateTime? EndDate
        {
            get
            {
                return this._endDate;
            }
            set
            {
                this._endDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the display name of the Fragment.
        /// </summary>
        /// <value>The display name of the Fragment.</value>
        public string FragmentDisplayName
        {
            get
            {
                return this._fragmentDisplayName;
            }
            set
            {
                this._fragmentDisplayName = value;
            }
        }

        /// <summary>
        /// Gets or sets the Fragment ID.
        /// </summary>
        /// <value>The Fragment ID.</value>
        public int? FragmentId
        {
            get
            {
                return this._fragmentId;
            }
            set
            {
                this._fragmentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the Fragment.
        /// </summary>
        /// <value>The name of the Fragment.</value>
        public string FragmentName
        {
            get
            {
                return this._fragmentName;
            }
            set
            {
                this._fragmentName = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Fragment is active.
        /// </summary>
        /// <value>The Fragment is active?</value>
        public bool? IsActive
        {
            get
            {
                return this._isActive;
            }
            set
            {
                this._isActive = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Fragment is next
        /// with respect to another Fragment.
        /// </summary>
        /// <value>The Fragment is next?</value>
        public bool? IsNext
        {
            get
            {
                return this._isNext;
            }
            set
            {
                this._isNext = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Fragment is previous
        /// with respect to another Fragment.
        /// </summary>
        /// <value>The Fragment is previous?</value>
        public bool? IsPrevious
        {
            get
            {
                return this._isPrevious;
            }
            set
            {
                this._isPrevious = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the Fragment is a wrapper.
        /// </summary>
        /// <value>The Fragment is a wrapper?</value>
        public bool? IsWrapper
        {
            get
            {
                return this._isWrapper;
            }
            set
            {
                this._isWrapper = value;
            }
        }

        /// <summary>
        /// Gets or sets the item characters.
        /// </summary>
        /// <value>The item characters.</value>
        public string ItemChar
        {
            get
            {
                return this._itemChar;
            }
            set
            {
                this._itemChar = value;
            }
        }

        /// <summary>
        /// Gets or sets the item text.
        /// </summary>
        /// <value>The item text.</value>
        public string ItemText
        {
            get
            {
                return this._itemText;
            }
            set
            {
                this._itemText = value;
            }
        }

        /// <summary>
        /// Gets or sets the modification date.
        /// </summary>
        /// <value>The modification date.</value>
        public DateTime? ModificationDate
        {
            get
            {
                return this._modificationDate;
            }
            set
            {
                this._modificationDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the next Fragment ID.
        /// </summary>
        /// <value>The next Fragment ID.</value>
        public int? NextFragmentId
        {
            get
            {
                return this._nextFragmentId;
            }
            set
            {
                this._nextFragmentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the Previous Fragment ID.
        /// </summary>
        /// <value>The Previous Fragment ID.</value>
        public int? PrevFragmentId
        {
            get
            {
                return this._prevFragmentId;
            }
            set
            {
                this._prevFragmentId = value;
            }
        }

        /// <summary>
        /// Gets or sets the sort ordinal.
        /// </summary>
        /// <value>The sort ordinal.</value>
        public byte? SortOrdinal
        {
            get
            {
                return this._sortOrdinal;
            }
            set
            {
                this._sortOrdinal = value;
            }
        }

        #endregion

        private DateTime? _createDate = null;
        private int? _documentId = null;
        private DateTime? _endDate = null;
        private string _fragmentDisplayName = String.Empty;
        private int? _fragmentId = null;
        private string _fragmentName = String.Empty;
        private bool? _isActive = null;
        private bool? _isNext = null;
        private bool? _isPrevious = null;
        private bool? _isWrapper = null;
        private string _itemChar = String.Empty;
        private string _itemText = String.Empty;
        private DateTime? _modificationDate = null;
        private int? _nextFragmentId = null;
        private int? _prevFragmentId = null;
        private byte? _sortOrdinal = null;
        private string _clientId = String.Empty;
    }
}
